


import bpy
import numpy as np
from itertools import chain

from 全局控制.Node.节点和插座基类.bl_UpdateNode import *
from 对象操作 import bl_对象变换帧

import 全局控制.Node.节点和插座基类.bl_节点基类 as 基类
from 全局控制.Node.节点数据类型 import bl_集合数据类型

from bpy.types import Operator, Menu
from 全局控制.Node.数据编辑.物体 import bl_修改器公共选项



E_粒子物理类型枚举 = [
	("NO", "None", "", 0),
	("NEWTON", "牛顿", "", 1),
	("KEYED", "键控", "", 2),
	("BOIDS", "群体", "", 3),
	("FLUID", "流体", "", 4),
]

E_粒子渲染类型枚举 = [
	("NONE", "None", "", 0),
	("HALO", "光晕", "", 1),
	("LINE", "线", "", 2),
	("PATH", "路径", "", 3),
	("OBJECT", "物体", "", 4),
	("COLLECTION", "容器组", "", 5),
	("BILLBOARD", "方板", "", 6),
]

E_粒子流体解算器类型枚举 = [
	("DDR", "DDR", "", 0),
	("CLASSICAL", "CLASSICAL", "", 1),
]




def f_投影物体数量update(self, context):
	差数 = len(self.m_投影物体) - self.m_projector_count
	print('差数 = ', 差数)
	if 差数 > 0 :
		for i in range(差数):
			self.m_投影物体.remove(len(self.m_投影物体)-1)
	else:
		差数 = -差数
		for i in range(差数):
			self.m_投影物体.add()

class C_Node_粒子系统修改器(基类.C_SN_基类):
	bl_dname = 'bl_node_粒子系统修改器'
	bl_label = '粒子系统'
	
	m_修改器名称 = bpy.props.StringProperty(name="修改器名称", default='粒子')
	m_是否渲染 = bpy.props.BoolProperty(default=True)
	m_是否显示 = bpy.props.BoolProperty(default=True)
	
	m_物理类型 = bpy.props.EnumProperty(items=E_粒子物理类型枚举, name="物理类型", default="NO" )
	m_渲染类型 = bpy.props.EnumProperty(items=E_粒子渲染类型枚举, name="渲染类型", default="NONE" )

	m_粒子流体解算器类型枚举 = bpy.props.EnumProperty(items=E_粒子流体解算器类型枚举, name="流体解算器类型", default="DDR" )

	m_投影物体 = bpy.props.CollectionProperty(type=bl_集合数据类型.C_物体组元素)
	m_projector_count = bpy.props.IntProperty(update=f_投影物体数量update, min=0, max=4096)
	



	def init(self, context):
		super(C_Node_粒子系统修改器, self).f_init(context)

		self.inputs.new('C_NodeSocket_文本', name='更新代码')

		self.inputs.new('C_NodeSocket_物体', name='修改对象')
		self.inputs.new('C_插座_List_i', name='数量')
		self.inputs.new('C_插座_List_i', name='随机种')
		self.inputs.new('C_插座_List_f', name='起始帧')
		self.inputs.new('C_插座_List_f', name='结束帧')
		self.inputs.new('C_插座_List_f', name='粒子寿命')
		self.inputs.new('C_插座_List_f', name='随机寿命')

		#速度
		self.inputs.new('C_插座_List_f', name='法线方向速度')
		self.inputs.new('C_Socket1D_Vec3', name='速度对齐因子')
		self.inputs.new('C_插座_List_f', name='随机方向')


		#粒子物体渲染参数
		self.inputs.new('C_NodeSocket_物体', name='渲染物体')
		self.inputs.new('C_插座_List_f', name='渲染大小')
		self.inputs.new('C_插座_List_f', name='随机大小')

		#力场权重
		self.inputs.new('C_插座_List_f', name='粒子质量')
		self.inputs.new('C_插座_List_f', name='重力')

		#流体力场属性
		self.inputs.new('C_插座_List_f', name='硬度')
		self.inputs.new('C_插座_List_f', name='粘度')
		self.inputs.new('C_插座_List_f', name='浮力')

		self.inputs.new('C_插座_List_f', name='斥力')
		self.inputs.new('C_插座_List_f', name='半径')
		self.inputs.new('C_插座_List_f', name='密度')



		self.outputs.new('C_NodeSocket_粒子', name='粒子系统')




		
		self.inputs['起始帧'].f_setData(1.0)
		self.inputs['结束帧'].f_setData(100.0)

		self.inputs['随机大小'].f_setData(0.0)
		self.inputs['渲染大小'].f_setData(0.1)
		#self.inputs['轮廓'].f_setData(0.5)
		#self.inputs['材质'].f_setData(-1)
		#self.inputs['切顶点'].f_setData(False)
		#self.inputs['use_clamp_overlap'].f_setData(True)
		#self.inputs['loop_slide'].f_setData(True)
		#self.inputs['mark_seam'].f_setData(False)
		#self.inputs['mark_sharp'].f_setData(False)


	def draw_buttons(self, context, layout):
		bl_修改器公共选项.f_可视选项绘制(self, layout)
		
		layout.separator()

		layout.prop(self, 'm_渲染类型')

		layout.separator()
		layout.prop(self, 'm_物理类型')
		if self.m_物理类型 == 'NEWTON':
			pass
			#layout.prop(self, 'm_限定方式', expand=True, toggle=True)
		elif self.m_物理类型 == 'FLUID':
			box = layout.box()
			流体UI布局 = box.row()
			流体UI布局.prop(self, 'm_粒子流体解算器类型枚举')
		

			
	def update(self):
		pass
	def f_插座数据是否独立(self, name, 对象数量):
		data = self.inputs[name].f_getData()
		num = len(data)
		if num == 对象数量:
			是否独立 = True
		else:
			if num == 0:
				data = 0
			else:
				data = data[0]
			是否独立 = False
		return data, 是否独立

	def f_update(self, 是否向下传递=False, input插座=None):
		修改对象 = self.inputs['修改对象'].f_getData()
		对象数量 = len(修改对象)
		if 对象数量 <= 0 : return False
		
		#修改对象 = list(chain(*修改对象))

		数量, 数量是否独立 = self.f_插座数据是否独立('数量', 对象数量)
		起始帧, 起始帧是否独立 = self.f_插座数据是否独立('起始帧', 对象数量)
		结束帧, 结束帧是否独立 = self.f_插座数据是否独立('结束帧', 对象数量)
		粒子寿命, 粒子寿命是否独立 = self.f_插座数据是否独立('粒子寿命', 对象数量)
		随机寿命, 随机寿命是否独立 = self.f_插座数据是否独立('随机寿命', 对象数量)
		
		
		法线方向速度, 法线方向速度是否独立 = self.f_插座数据是否独立('法线方向速度', 对象数量)
		速度对齐因子, 速度对齐因子是否独立 = self.f_插座数据是否独立('速度对齐因子', 对象数量)
		随机方向, 随机方向是否独立 = self.f_插座数据是否独立('随机方向', 对象数量)


		粒子质量, 粒子质量是否独立 = self.f_插座数据是否独立('粒子质量', 对象数量)
		

		if self.m_物理类型 == 'FLUID' :
			硬度, 硬度是否独立 = self.f_插座数据是否独立('硬度', 对象数量)
			粘度, 粘度是否独立 = self.f_插座数据是否独立('粘度', 对象数量)
			浮力, 浮力是否独立 = self.f_插座数据是否独立('浮力', 对象数量)
			斥力, 斥力是否独立 = self.f_插座数据是否独立('斥力', 对象数量)
			
			半径, 半径是否独立 = self.f_插座数据是否独立('半径', 对象数量)
			密度, 密度是否独立 = self.f_插座数据是否独立('密度', 对象数量)
		


		if self.m_渲染类型 != 'OBJECT':
			obj = self.inputs['渲染物体'].f_getData()
			try:
				obj = obj[0]
			except :
				print('err! : 粒子物体实例渲染 没有物体')
			



		
		粒子系统 = []
		index = 0
		for obj in 修改对象:
			修改器 = bl_修改器公共选项.f_修改器添加(self, obj, 'PARTICLE_SYSTEM')
			粒子配置 = 修改器.particle_system.settings

			if 数量是否独立 :
				修改器.particle_system.settings.count = 数量[index]
			else:
				修改器.particle_system.settings.count = 数量
				
			if 起始帧是否独立 :
				修改器.particle_system.settings.frame_start = 起始帧[index]
			else:
				修改器.particle_system.settings.frame_start = 起始帧
			
			if 结束帧是否独立 :
				修改器.particle_system.settings.frame_end = 结束帧[index]
			else:
				修改器.particle_system.settings.frame_end = 结束帧

			if 粒子寿命是否独立 :
				修改器.particle_system.settings.lifetime = 粒子寿命[index]
			else:
				修改器.particle_system.settings.lifetime = 粒子寿命

			if 随机寿命是否独立:
				修改器.particle_system.settings.lifetime_random = 随机寿命[index]
			else:
				修改器.particle_system.settings.lifetime_random = 随机寿命

			if 法线方向速度是否独立:
				修改器.particle_system.settings.normal_factor = 法线方向速度[index]
			else:
				修改器.particle_system.settings.normal_factor = 法线方向速度
			
			if 速度对齐因子是否独立:
				修改器.particle_system.settings.object_align_factor = 速度对齐因子[index]
			else:
				修改器.particle_system.settings.object_align_factor = 速度对齐因子

			if 随机方向是否独立:
				修改器.particle_system.settings.factor_random = 随机方向[index]
			else:
				修改器.particle_system.settings.factor_random = 随机方向



			修改器.particle_system.settings.physics_type = self.m_物理类型
			if self.m_物理类型 != 'NO':
				if 粒子质量是否独立 :
					修改器.particle_system.settings.mass = 粒子质量[index]
				else:
					修改器.particle_system.settings.mass = 粒子质量
				if self.m_物理类型 == 'NEWTON' :
					pass
				elif self.m_物理类型 == 'FLUID' :
					if 硬度是否独立 :
						修改器.particle_system.settings.fluid.stiffness = 硬度[index]
					else:
						修改器.particle_system.settings.fluid.stiffness = 硬度
					
					if 粘度是否独立 :
						修改器.particle_system.settings.fluid.linear_viscosity = 粘度[index]
					else:
						修改器.particle_system.settings.fluid.linear_viscosity = 粘度

					if 浮力是否独立 :
						修改器.particle_system.settings.fluid.buoyancy = 浮力[index]
					else:
						修改器.particle_system.settings.fluid.buoyancy = 浮力

					if 斥力是否独立 :
						修改器.particle_system.settings.fluid.repulsion = 斥力[index]
					else:
						修改器.particle_system.settings.fluid.repulsion = 斥力

					if 半径是否独立 :
						修改器.particle_system.settings.fluid.fluid_radius = 半径[index]
					else:
						修改器.particle_system.settings.fluid.fluid_radius = 半径

					if 密度是否独立 :
						修改器.particle_system.settings.fluid.rest_density = 密度[index]
					else:
						修改器.particle_system.settings.fluid.rest_density = 密度

				
			if self.m_渲染类型 != 'NO':
				if self.m_渲染类型 != 'OBJECT':
					粒子配置.instance_object = obj
					



			粒子系统.append(修改器.particle_system.settings)
			
			index += 1


		self.outputs['粒子系统'].f_setData(粒子系统)

		super(C_Node_粒子系统修改器, self).f_update(是否向下传递, input插座)


	


class C_NODE_MENU_粒子系统修改器(bpy.types.Operator):
	bl_idname = 'node.global_node_obj_modifiers_particle'
	bl_label = '粒子系统修改器'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_Node_粒子系统修改器', use_transform=True)
		return {'FINISHED'}
		




classes = (
	C_Node_粒子系统修改器,
	C_NODE_MENU_粒子系统修改器,
	
)

def register():
	for c in classes:
		bpy.utils.register_class(c)
		
def unregister():
	for c in classes:
		bpy.utils.unregister_class(c)



